  

// Here I am going to create the Course class.
function CourseFromJSON(j)
{
	return new Course(j.id, j.title, j.acronym, j.number, j.credits, j.description, j.prereqs, j);
}

function Course(id, title, acronym, number, credits, description, prereqs, j){
	this.id = id;
	this.title = title;
	this.acronym = acronym;
	this.number = number;
	this.credits = credits;
	this.description = description;
    this.prereqs = prereqs.split(",");
    this.prereqs_string = prereqs
    
    for(s in this.prereqs)
    {
    	this.prereqs[s] = this.prereqs[s].split(" ");
    }

	this.is_alerted = false;
	this.alert_text = false;
	this.j = j
	
	// j holds the json representation of a course
	this.display_course_search = function(){
		output = '<tr style="semester_course_row" title="' + this.description + '"><td>' + this.title + "(" + this.acronym + " " + this.number;
		output += ")</td>";
		
		output += "<td>" + this.credits + "</td>";
		
		// This line must be dependent on the row the course is in, so we may have to do a callback function
		// with jQuery later. Leave it for now though.
		output += '<td><input type="checkbox" class=\'search_checkbox\' value=\'' + JSON.stringify(this.j) + '\' /></td></tr>';
		
		return output;
	}
	
	this.display_course_with_class = function(semester, class_string)
	{
		if(this.is_alerted == true)
		{
		    class_string = "semester_course_row_red";
		}

        output = '<tr class="' + class_string + '" title="' + this.description + '"><td>' + this.title + "(" + this.acronym + " " + this.number;
		output += ")</td>";
		
		output += "<td>" + this.credits + "</td>";
		
		// This line must be dependent on the row the course is in, so we may have to do a callback function
		// with jQuery later. Leave it for now though.
		output += '<td><input type="button" class="noprint" value="X" onclick="remove_course_from_schedule(\'' + semester + '\', ' + id + ');" />';
		output += "</td></tr>";
		
		return output;
	}
	
	this.get_prereqs = function()
	{
		return this.prereqs;
	}
		
}

function add_course_to_semester_no_check(semester, j)
{
    add_course_to_schedule(semester, j, false);
}

function add_course_to_semester(semester, j)
{
    // CHANGE THIS TO TRUE WHEN PREREQ CHECKS WORK
    add_course_to_schedule(semester, j, true);
}

function add_course_to_schedule(semester, j, check)
{	    
	sem = schedule["s" + semester];
	
	// prerequisite checking
	var course = CourseFromJSON(j);
	
	var is_met_array = new Array();
	var is_met = false;
    // i is the list of prereq sets, j iseach course in a set
    
	if(course.prereqs_string != "" && check) {
        for(i in course.prereqs){
            
            prereqs_met = new Array();
            
            for (j in course.prereqs[i]) {
                
                prereq_course = course.prereqs[i][j];
                
                // Look at each semester. If the prereq is met in a semester, and that semester id
                // is less than the one we are trying to add to...
                
                for (s in schedule) {
                    id = schedule[s].semester_number;
                    
                    if(id >= semester) {
                        continue;
                    }
                    
                    if(schedule[s].contains(prereq_course)){
                        prereqs_met.push(prereq_course);
                        break;
                    }	
                }
            }
            
            if(prereqs_met.length == course.prereqs[i].length)
            {
                is_met = true;
                break;
            }
        }
        if(!is_met){
            course.is_alerted = true;
            course.alert_text = "The prerequisites for this course have not been met.";
            alert(course.alert_text);
        }
    }
    
	sem.add_course(course);
	
	update_schedule_lists();
}

function clean_semester(semester)
{
	// the inputs that call this already have "s" tacked onto the front
	sem = schedule[semester];
	
	sem.clean_semester();
	
	update_schedule_lists();
}

function remove_course_from_schedule(semester, id)
{
	// the inputs that call this already have "s" tacked onto the front

	    
	sem = schedule[semester];

	sem.remove_course(id);
	
	update_schedule_lists();
	update_checkboxes();
}


function update_schedule_lists()
{
	for(i in schedule)
	{

		$('#semester_' + i + " tbody").html("");
		sem = schedule[i]; // should be an array
		
		$('#semester_' + i + " tbody").append(sem.display_schedule_semester());
	}
}

function update_checkboxes()
{
	sem = schedule["s-1"];
	$(".course_checkbox").each(function() {
		course = JSON.parse($(this).attr('value'));
		$(this).attr('checked', false);

		if(sem.contains(course.id))
		{
			$(this).attr('checked', true);
		}
		
	})
}

// {"s0":[{"id":"177","acronym":"AMST","number":"100","title":"Ideas and Images in American Culture. ","description":" GEP\/GFR: Meets AH. A broad introduction to the study of American culture, past and present. The course focuses upon primary ideas that have been most influential in the development of American culture and their expression in various forms, written and visual. Special emphasis is placed upon tensions between the individual and society and upon the relationship of culture to subcultures. Notes: ","credits":"3"},{"id":"420","acronym":"CHEM","number":"300","title":"Analytical Chemistry. ","description":" A lecture-laboratory course covering the theory and practice of quantitative chemical analysis. The emphasis is on homogeneous and heterogeneous equibilibria involved in gravimetric and volumetric methods. Introduction to instrumental techniques includes potentiometry, spectrophotometry and chromatographic separations. (Fall\/Spring)  Notes: ","credits":"4"}],"s1":[{"id":"179","acronym":"AMST","number":"210","title":"Introduction to Lesbian and Gay Studies. ","description":" GEP\/GFR: Meets SS This course examines various lesbian and gay experiences in contemporary American society. Using an interdisciplinary approach, the course examines historical origins and precedents, theoretical frameworks and contemporary case studies to understand the issues affecting the social relations between American society and lesbians and gays. Primary goals of the course are to conduct a critical inquiry into the patterns of lesbians? and gays? subordinate status, to explain their origins and persistence and to consider various routes for changing these patterns. Throughout the course, special attention will be given to the diverse experiences of lesbians and gays based on race, class and disability.  Notes: Also listed as GWST 210.","credits":"3"},{"id":"241","acronym":"ANTH","number":"211","title":"Cultural Anthropology. ","description":" GEP\/GFR: SS or C. An introduction to the central concepts and issues in cultural anthropology. The course employs a worldwide comparative perspective that examines topics such as: the concept of culture, cultural-ecological systems and family organization; magic, religion and witchcraft; socialization, personality and mental illness; conflict resolution and warfare. Notes: ","credits":"3"}],"s2":[],"s3":[{"id":"241","acronym":"ANTH","number":"211","title":"Cultural Anthropology. ","description":" GEP\/GFR: SS or C. An introduction to the central concepts and issues in cultural anthropology. The course employs a worldwide comparative perspective that examines topics such as: the concept of culture, cultural-ecological systems and family organization; magic, religion and witchcraft; socialization, personality and mental illness; conflict resolution and warfare. Notes: ","credits":"3"}],"s4":[],"s5":[]}

function reset_stored_schedule()
{
	$.getJSON("/json_utils.php",{task: 'get_classes_by_semester'}, function(j){
      semester_array_with_courses = j;
	  schedule = new Array();
	  for(i in semester_array_with_courses)
	  {  
	  	sem = semester_array_with_courses[i];
		courses = new Array();
		for(k in sem)
		{
			courses.push(CourseFromJSON(sem[k]));
		}
		schedule[i] = new Semester(i, courses);
	  }
      update_schedule_lists();
    });
}


function generate_schedule()
{
	$.getJSON("/json_utils.php",{task: 'get_remaining_requirements'}, function(j){
	
	  // the courses we still have left to take
      remaining = j;
      
      // Clear out the 0+ semesters.
	  
	  for(s in schedule) {
        sem = schedule[s]
        
        if(sem.semester_number >= 0)
            sem.clean_schedule();
	  }
	  update_schedule_lists();
	  
	  //alert(JSON.stringify(remaining));
	  courses = new Array();
	  for(i in remaining)
	  {  
        courses.push(CourseFromJSON(remaining[i]));
	  }
	
	  courses = courses.sort(course_compare);
	  
	  x = "";
	  for(i in courses)
	  {
	    x += courses[i].acronym + " " + courses[i].number + ", ";
	    add_course_to_schedule_generate(courses[i]);
	  
	  }
	 
	  
      update_schedule_lists();
    });
}

// will sort courses by number ascending
function course_compare(a, b)
{
    return getInt(a.number.charAt(0)) - getInt(b.number.charAt(0));
}

function getInt(chr)
{
    x = parseInt(chr);
    if(isNaN(x))
        x = 3;
    
    return x;
}


function add_course_to_schedule_generate_id(id)
{
    $.ajaxSetup({'async': false});
    semester = -4;
    
    $.getJSON("/json_utils.php",{task: 'course_object', course_id: id}, function(j){
          // j contains a json object with all of the elements of an individual class
          semester = add_course_to_schedule_generate(CourseFromJSON(j));
          
        })
        
   return semester;
}

function add_course_to_schedule_generate(course)
{	    
    add_later_than = -1;
    
	if(course.prereqs_string != "") {
	    // Add the courses from the first set of prereqs
	    prereqs = course.prereqs[0]
        for (j in prereqs) {
            prereq_course = prereqs[j];
            loc = find_course_in_schedule(prereq_course);
            
            if(loc == false){
                add_course_to_schedule_generate_id(prereq_course);
            }
            
            loc = find_course_in_schedule(prereq_course);
            if(loc > add_later_than)
                add_later_than = loc;
            
        }
    }
    
    for(s in schedule) {
        sem = schedule[s]
        
        if(sem.contains(course.id))
            break;
        
        if(sem.semester_number <= add_later_than)
            continue;
        
        if((sem.get_credits() + parseInt(course.credits)) <= 16)
        {
            sem.add_course(course);
            return sem.semester_number;
        }
    } 
	
}

function find_course_in_schedule(course)
{
    loc = false;
    
    for (s in schedule) {
        id = schedule[s].semester_number;
                
        if(schedule[s].contains(course)){
            loc = id;
            break;
        }	
   }
   
   return loc;
}

function reset_stored_history()
{
	$.getJSON("/json_utils.php",{task: 'get_history'}, function(j){
		var semester_array_with_courses = j;
		  schedule = new Array();
		  for(i in semester_array_with_courses)
		  {  
		  	var sem = semester_array_with_courses[i];
			var courses = new Array();
			for(k in sem)
			{
				courses.push(CourseFromJSON(sem[k]));
			}
			schedule[i] = new Semester(i, courses);
		  }
      update_schedule_lists();
      update_checkboxes();
    });
}


function save_history()
{
	save_courses("save_history");
}

function save_schedule()
{
	save_courses("save_schedule");
}

function save_courses(action)
{
	// when saving, we only need to send the ids in an array in an array of semestesr like
	// [ [{ "id": "176"}, {"id" : "1667"}], [{"id" : ..}] ]
	
	var to_save_schedule = [];
	
	for(i in schedule)
	{
		semester = schedule[i].courses;
        
		// for each course in the semester, add the id
		for(j in semester)
		{
			to_push = new Object();
			to_push.sem = i;
			to_push.id = semester[j]["id"];
			to_save_schedule.push(to_push);
		}
			
	}
	
	
	$.getJSON("/json_utils.php",{task: action, data: JSON.stringify(to_save_schedule)}, function(j){
      
      schedule = j.data;
      message = j.message;
      
      if(jQuery.trim(message) != "")
      {
      	 alert(message);
      }
      
      if(action == "save_history")
      {
        reset_stored_history();
      
      }
      else
      {
        reset_stored_schedule();
      }
    });
}



// This makes a JSON call to get the course ids and numbers based on the acronym.
// We then populate the dropdown box.
$(function(){
  $("select.acronym").change(function(){
  	var semester_id = $(this).attr('title');
  	if($(this).val() == "Choose") return;

    $.getJSON("/json_utils.php",{task: 'course_numbers', acronym: $(this).val()}, function(j){
      var options = '';
      for (var i = 0; i < j.length; i++) {
        options += '<option value="' + j[i].course_id + '">' + j[i].number + '</option>';
      }

      $("#numbers" + semester_id).html(options);
    })

  })
})

// When this is clicked, a course gets added to a certain semester. This updates the current
// schedule.
$(function(){
  $(".add_class").click(function(){
    var semester_id = $(this).attr('title');
    if($("#numbers"+semester_id).val() == undefined)
    {
        alert("Please select a course to add.");
    }
    else
    {
        $.getJSON("/json_utils.php",{task: 'course_object', course_id: $("#numbers"+semester_id).val()}, function(j){
          // j contains a json object with all of the elements of an individual class
          
          // We only do the check if we are doing future schedule.\
          
          if(parseInt(semester_id) < 0)
          {
            add_course_to_semester_no_check(semester_id, j);
          }
          else
          {
            add_course_to_semester(semester_id, j);
          }
          
        })
     }

  })
})

// Semester class - constructor takes an array of courses
function Semester(semester_name, courses) {
	
	this.semester_name = semester_name;
	this.semester_number = parseInt(semester_name.substr(1));
	this.courses = courses;

		// displays a schedule for a semester with heading
	this.display_schedule_semester = function()
	{
		output = "";
		var credits = 0;
		for (var i in this.courses)
		{
			course = this.courses[i];
			output += course.display_course_with_class(this.semester_name, "");
			credits += parseInt(course.credits);
		}
		 output += ' <tr class="semester_cap">' + 
			    '<td>Semester Totals</td>' +
			    '<td>' + credits + '</td>' +
			    '<td>&nbsp;</td>' +
			  '</tr></table>';
		 return output;
	}
	
	this.get_credits = function()
	{
	    credits = 0;
        for (var i in this.courses)
        {
            course = this.courses[i];
            credits += parseInt(course.credits);
        }
	    return credits;
	}
	
	// returns a string of 
	this.display_schedule = function()
	{
		output = "";
		var credits = 0;
		for (var i in this.courses)
		{
			course = this.courses[i];
			output += course.display_course_with_class(semester_name, "semester_course_row");
			credits += parseInt(course.credits);
		}
		 output += ' <tr class="semester_cap">' + 
			    '<td>Semester Totals</td>' +
			    '<td>' + credits + '</td>' +
			    '<td>&nbsp;</td>' +
			  '</tr></table>';
		 return output; 
	}
	
	this.add_course = function(course)
	{
		if (!this.contains(course.id))
		 {
			this.courses.push(course);
		}
	}
	
	this.remove_course = function(course_id)
	{
		sem = this.courses;
		
		for(i=0; i < sem.length; i++)
        {
            // remove the matching class, leaving sem[i] undefined.
            if(sem[i].id == course_id)
            {
                sem.splice(i, 1);
                break;
            }
    
	    }
	}
	
	this.contains = function(course_id)
	{
		for(var i in this.courses)
		{
		    course = this.courses[i];
			if(course_id == course.id)
			{
				return true;
			}
		}
		return false;
	}
	
	// empties the semester
	this.clean_schedule = function()
	{
		this.courses = new Array();
	}
	
	this.toString = function()
	{
		return "Semester";
	}
	
}


